home *** CD-ROM | disk | FTP | other *** search
/ Team Palmtops 7 / Palmtops_numero07.iso / WinCE / SDKWindowsCE / HandHeldPCPro30 / sdk.exe / Jupiter SDK / data1.cab / MFC / src / wcetime.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-19  |  10.0 KB  |  387 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.             
  13. const __int64 n1SecIn100NS = (__int64)10000000;
  14.  
  15. static __int64 wce_GetDeltaSecs(FILETIME f1, FILETIME f2)
  16. {
  17.     // Stuff the 2 FILETIMEs into their own __int64s.
  18.     __int64 t1 = f1.dwHighDateTime;
  19.     t1 <<= 32;                
  20.     t1 |= f1.dwLowDateTime;
  21.  
  22.     __int64 t2 = f2.dwHighDateTime;
  23.     t2 <<= 32;                
  24.     t2 |= f2.dwLowDateTime;
  25.  
  26.     // Take the difference of 64-bit ints.
  27.     // This should be the number of 100-nanosecond intervals since Jan. 1970.
  28.     // Divide by 10,000,000 to get the number of seconds since Jan. 1970.
  29.     __int64 iTimeDiff = (t2 - t1) / n1SecIn100NS;
  30.     return iTimeDiff;
  31. }
  32.  
  33. static SYSTEMTIME wce_TmToSystemTime(tm &t)
  34. {
  35.     SYSTEMTIME s;
  36.  
  37.     s.wYear      = t.tm_year + 1900;
  38.     s.wMonth     = t.tm_mon+1;
  39.     s.wDayOfWeek = t.tm_wday;
  40.     s.wDay       = t.tm_mday;
  41.     s.wHour      = t.tm_hour;
  42.     s.wMinute    = t.tm_min;
  43.     s.wSecond    = t.tm_sec;
  44.     s.wMilliseconds = 0; //ignored
  45.     // t.tm_yday is not used in SYSTEMTIME
  46.  
  47.     return s;
  48. }
  49.  
  50. static FILETIME wce_YearToFileTime(WORD wYear)
  51. {    
  52.     SYSTEMTIME sbase;
  53.  
  54.     sbase.wYear         = wYear;
  55.     sbase.wMonth        = 1;
  56.     sbase.wDayOfWeek    = 1; //assumed
  57.     sbase.wDay          = 1;
  58.     sbase.wHour         = 0;
  59.     sbase.wMinute       = 0;
  60.     sbase.wSecond       = 0;
  61.     sbase.wMilliseconds = 0;
  62.  
  63.     FILETIME fbase;
  64.     SystemTimeToFileTime( &sbase, &fbase );
  65.  
  66.     return fbase;
  67. }
  68.  
  69. static FILETIME wce_Int64ToFileTime(__int64 iTime)
  70. {
  71.     FILETIME f;
  72.  
  73.     f.dwHighDateTime = (DWORD)((iTime >> 32) & 0x00000000FFFFFFFF);
  74.     f.dwLowDateTime  = (DWORD)( iTime        & 0x00000000FFFFFFFF);
  75.  
  76.     return f;
  77. }
  78.  
  79.  
  80. static time_t wce_SystemTimeToYDay(SYSTEMTIME s)
  81. {
  82.     FILETIME fMidnightJan1 = wce_YearToFileTime(s.wYear);
  83.     FILETIME f;              SystemTimeToFileTime(&s, &f);
  84.     return (time_t)(wce_GetDeltaSecs(fMidnightJan1, f) / (__int64)86400);
  85. }
  86.  
  87. static tm wce_SystemTimeToTm(SYSTEMTIME &s)
  88. {
  89.     tm t;
  90.  
  91.     t.tm_year  = s.wYear - 1900;
  92.     t.tm_mon   = s.wMonth-1;
  93.     t.tm_wday  = s.wDayOfWeek;
  94.     t.tm_mday  = s.wDay;
  95.     t.tm_yday  = wce_SystemTimeToYDay(s);
  96.     t.tm_hour  = s.wHour;
  97.     t.tm_min   = s.wMinute;
  98.     t.tm_sec   = s.wSecond;
  99.     t.tm_isdst = 0; // ignored
  100.  
  101.     return t;
  102. }
  103.  
  104. static TIME_ZONE_INFORMATION g_TZInfoCache; // okay to not be thread-safe
  105. static BOOL g_bTZInfoCacheInitialized = FALSE;
  106. __declspec(dllexport) BOOL g_bUseDST = TRUE;
  107.  
  108. static void wce_GetTZBias(time_t* pTZBiasSecs = NULL, int* pDSTBiasSecs = NULL)
  109. {
  110.     if(!g_bTZInfoCacheInitialized)
  111.     {
  112.         // WinCE: GetTimeZoneInformation is expensive, so we call it only once.
  113.         if(GetTimeZoneInformation(&g_TZInfoCache) == 0xFFFFFFFF)
  114.             return;
  115.         g_bTZInfoCacheInitialized = TRUE;
  116.     }
  117.  
  118.     if(pTZBiasSecs != NULL)
  119.     {
  120.         *pTZBiasSecs = g_TZInfoCache.Bias * 60L;
  121.         if (g_TZInfoCache.StandardDate.wMonth != 0)
  122.             *pTZBiasSecs += (g_TZInfoCache.StandardBias * 60L);
  123.     }
  124.  
  125.     if(pDSTBiasSecs != NULL)
  126.     {
  127.         if ((g_TZInfoCache.DaylightDate.wMonth != 0) && (g_TZInfoCache.DaylightBias != 0))
  128.             *pDSTBiasSecs = (g_TZInfoCache.DaylightBias - g_TZInfoCache.StandardBias) * 60L;
  129.         else
  130.             *pDSTBiasSecs = 0;
  131.     }
  132. }
  133.  
  134.  
  135. typedef struct {
  136.         int  yr;        // year of interest
  137.         int  yd;        // day of year 
  138.         long ms;        // milli-seconds in the day 
  139. } transitionTime;
  140.  
  141. static void wce_cvtdate (int trantype, int year, int month, int week, int dayofweek,
  142.                          int date, int hour, int min, int sec, int msec,
  143.                          transitionTime* pDST)
  144. {
  145.     const int days[]           = {-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364};
  146.     const int leapYearDays[]   = {-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
  147.     const int DAY_MILLISEC     = (24L * 60L * 60L * 1000L);
  148.     const int BASE_DOW         = 4; // 01-01-70 was a Thursday 
  149.     const int LEAP_YEAR_ADJUST = 17L; // Leap years 1900 - 1970
  150.     BOOL bIsLeapYear = ((year & 3) == 0);
  151.  
  152.     int yearday;
  153.     int monthdow;
  154.     int DSTBiasSecs;
  155.     wce_GetTZBias(NULL, &DSTBiasSecs);
  156.  
  157.     yearday = 1 + (bIsLeapYear ? leapYearDays[month - 1] : days[month - 1]);
  158.     monthdow = (yearday + ((year - 70) * 365) + ((year - 1) >> 2) -
  159.                 LEAP_YEAR_ADJUST + BASE_DOW) % 7;
  160.     if ( monthdow < dayofweek )
  161.         yearday += (dayofweek - monthdow) + (week - 1) * 7;
  162.     else
  163.         yearday += (dayofweek - monthdow) + week * 7;
  164.  
  165.     if ((week == 5) && (yearday > (bIsLeapYear ? leapYearDays[month] : days[month])))
  166.         yearday -= 7;
  167.  
  168.     if ( trantype == 1 ) 
  169.     {   // Converted date was for the start of DST
  170.         pDST->yd = yearday;
  171.         pDST->ms = (long)msec + (1000L * (sec + 60L * (min + 60L * hour)));
  172.         pDST->yr = year;
  173.     }
  174.     else 
  175.     {   // Converted date was for the end of DST
  176.         pDST->yd = yearday;
  177.         pDST->ms = (long)msec + (1000L * (sec + 60L * (min + 60L * hour)));
  178.         if ((pDST->ms += (DSTBiasSecs * 1000L)) < 0) 
  179.         {
  180.             pDST->ms += DAY_MILLISEC;
  181.             pDST->ms--;
  182.         }
  183.         else if (pDST->ms >= DAY_MILLISEC) 
  184.         {
  185.             pDST->ms -= DAY_MILLISEC;
  186.             pDST->ms++;
  187.         }
  188.         pDST->yr = year;
  189.     }
  190. }
  191.  
  192. int wce_isindst(struct tm *pt)
  193. {
  194.     transitionTime DSTStart = { -1, 0, 0L }, DSTEnd = { -1, 0, 0L };
  195.  
  196.     if(!g_bUseDST) 
  197.         return 0;
  198.  
  199.     if(!g_bTZInfoCacheInitialized)
  200.         wce_GetTZBias();
  201.  
  202.     if((pt->tm_year != DSTStart.yr) || (pt->tm_year != DSTEnd.yr)) 
  203.     {    
  204.         if (g_TZInfoCache.DaylightDate.wYear != 0 || g_TZInfoCache.StandardDate.wYear != 0)
  205.             return 0;
  206.  
  207.         wce_cvtdate(1,
  208.                     pt->tm_year,
  209.                     g_TZInfoCache.DaylightDate.wMonth,
  210.                     g_TZInfoCache.DaylightDate.wDay,
  211.                     g_TZInfoCache.DaylightDate.wDayOfWeek,
  212.                     0,
  213.                     g_TZInfoCache.DaylightDate.wHour,
  214.                     g_TZInfoCache.DaylightDate.wMinute,
  215.                     g_TZInfoCache.DaylightDate.wSecond,
  216.                     g_TZInfoCache.DaylightDate.wMilliseconds,
  217.                     &DSTStart);
  218.  
  219.         wce_cvtdate(0,
  220.                     pt->tm_year,
  221.                     g_TZInfoCache.StandardDate.wMonth,
  222.                     g_TZInfoCache.StandardDate.wDay,
  223.                     g_TZInfoCache.StandardDate.wDayOfWeek,
  224.                     0,
  225.                     g_TZInfoCache.StandardDate.wHour,
  226.                     g_TZInfoCache.StandardDate.wMinute,
  227.                     g_TZInfoCache.StandardDate.wSecond,
  228.                     g_TZInfoCache.StandardDate.wMilliseconds,
  229.                     &DSTEnd);
  230.     }
  231.  
  232.     if (DSTStart.yd < DSTEnd.yd) 
  233.     {
  234.         // Northern hemisphere ordering
  235.         if ((pt->tm_yday < DSTStart.yd) || (pt->tm_yday > DSTEnd.yd))
  236.             return 0;
  237.         if ((pt->tm_yday > DSTStart.yd) && (pt->tm_yday < DSTEnd.yd))
  238.             return 1;
  239.     }
  240.     else 
  241.     {
  242.         // Southern hemisphere ordering
  243.         if ( (pt->tm_yday < DSTEnd.yd) || (pt->tm_yday > DSTStart.yd) )
  244.             return 1;
  245.         if ( (pt->tm_yday > DSTEnd.yd) && (pt->tm_yday < DSTStart.yd) )
  246.             return 0;
  247.     }
  248.  
  249.     long ms = 1000L * (pt->tm_sec + 60L * pt->tm_min + 3600L * pt->tm_hour);
  250.  
  251.     if ( pt->tm_yday == DSTStart.yd ) 
  252.     {
  253.         if ( ms >= DSTStart.ms )
  254.             return 1;
  255.         else
  256.             return 0;
  257.     }
  258.     else 
  259.     {
  260.         // pt->tm_yday == DSTEnd.yd
  261.         if ( ms < DSTEnd.ms )
  262.             return 1;
  263.         else
  264.             return 0;
  265.     }
  266. }
  267.  
  268. long wce_GetMessageTime()
  269. {
  270.     SYSTEMTIME rSysTime;
  271.     long lTotalMsecs = 0;
  272.  
  273.     ::GetSystemTime( &rSysTime );
  274.  
  275.     // Msecs = hours * 60min/hr * 60sec/min * 1000mSec/sec
  276.     lTotalMsecs  = (long)rSysTime.wHour * 60L * 60L * 1000L;
  277.  
  278.     // Msecs = min              * 60sec/min * 1000mSec/sec
  279.     lTotalMsecs += (long)rSysTime.wMinute * 60L * 1000L;
  280.  
  281.     // Msecs = sec                          * 1000mSec/sec
  282.     lTotalMsecs += (long)rSysTime.wSecond * 1000L;
  283.  
  284.     // Msecs = mSecs
  285.     lTotalMsecs += (long)rSysTime.wMilliseconds;
  286.  
  287.     return (lTotalMsecs);
  288. }
  289.  
  290.  
  291. time_t wce_mktime(struct tm* pt)
  292. {
  293.     static const FILETIME f1970 = wce_YearToFileTime(1970);
  294.  
  295.     // Convert input tm to SYSTEMTIME
  296.     SYSTEMTIME s = wce_TmToSystemTime(*pt);
  297.  
  298.     // Fix the yday (needs to be correct in order for wce_isindst to work)
  299.     pt->tm_yday = wce_SystemTimeToYDay(s);
  300.  
  301.     // Convert SYSTEMTIME to FILETIME.
  302.     FILETIME f;
  303.     SystemTimeToFileTime( &s, &f );
  304.  
  305.     // Incorporate time zone and daylight savings time
  306.     time_t TZBiasSecs;
  307.     int    DSTBiasSecs;
  308.     wce_GetTZBias(&TZBiasSecs, &DSTBiasSecs);
  309.     if (wce_isindst(pt))
  310.         TZBiasSecs += DSTBiasSecs;
  311.     
  312.     // Get the number of seconds since Jan 1, 1970
  313.     return (time_t)(wce_GetDeltaSecs(f1970, f) + TZBiasSecs);
  314. }
  315.  
  316. tm* wce_localtime(const time_t *ptime)
  317. {
  318.     static const __int64 iOffset = 
  319.         wce_GetDeltaSecs(wce_YearToFileTime(1601), wce_YearToFileTime(1970));
  320.  
  321.     static tm  t;
  322.     FILETIME   f;
  323.     SYSTEMTIME s;
  324.     time_t     TZBiasSecs;
  325.     int        DSTBiasSecs;
  326.  
  327.     memset(&t, 0, sizeof(tm));
  328.     wce_GetTZBias(&TZBiasSecs, &DSTBiasSecs);
  329.  
  330.     // Set iTime to number of 100 nanosecond intervals since Jan. 1601.
  331.     __int64 iTime = ((__int64)*ptime + iOffset - (__int64)TZBiasSecs) * n1SecIn100NS;
  332.  
  333.     // Convert iTime to FILETIME
  334.     f = wce_Int64ToFileTime(iTime);
  335.  
  336.     // Convert the FILETIME to a SYSTEMTIME
  337.     if(FileTimeToSystemTime(&f, &s))
  338.     {
  339.         struct tm t2 = wce_SystemTimeToTm(s);
  340.         if(wce_isindst(&t2))
  341.         {
  342.             // Take DST into account
  343.             f = wce_Int64ToFileTime(iTime - DSTBiasSecs * n1SecIn100NS);
  344.             FileTimeToSystemTime(&f, &s);
  345.         }
  346.         t = wce_SystemTimeToTm(s);
  347.     }
  348.  
  349.     return &t;
  350. }
  351.  
  352. //problem4: we need DST computations included in the boundary cases... brute force test?
  353.  
  354.  
  355. time_t wce_time( time_t *timer )
  356. {
  357.     ASSERT(timer == NULL); // not supported
  358.     
  359.     SYSTEMTIME s;
  360.     GetLocalTime( &s );
  361.     tm t = wce_SystemTimeToTm(s);
  362.  
  363.     return wce_mktime( &t );
  364. }
  365.  
  366. char* wce_ctime( const time_t *ulSecsSince1970 )
  367. {
  368.     static TCHAR szBuf[28];
  369.     struct tm *ptime = wce_localtime(ulSecsSince1970);
  370.  
  371.     _tcsncpy(&szBuf[0], _T("Sun Mon Tue Wed Thu Fri Sat ") + (ptime->tm_wday*4), 4);
  372.     _tcsncpy(&szBuf[4], _T("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ") + (ptime->tm_mon*4), 4 );
  373.     wsprintf(&szBuf[8], _T("%02d %02d:%02d:%02d %04d\n") ,
  374.         ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec, ptime->tm_year+1900);
  375.  
  376.     // convert to ascii
  377.     TCHAR *szWide = szBuf;
  378.     char *szAscii = (char*)szBuf;
  379.     do
  380.     {
  381.         *szAscii++ = *(char*)szWide;
  382.     } while(*szWide++);
  383.  
  384.     return (char*)szBuf;
  385. }
  386.  
  387.